package drawingObjects;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

public class Text extends DrawingObject{

	private String text;
	private Point startPoint;
	private boolean dragging;
	private ArrayList<String> committedLines;
	
	public Text(int fontSize) {
		text = "";
		this.fontSize = fontSize;
		committedLines = new ArrayList<String>();
	}
	
	public Text() {
		text = "";
		committedLines = new ArrayList<String>();
	}
	
	public int fontSize = 12;
	
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Font font = new Font("Serif", Font.PLAIN, fontSize);
		g.setFont(font);
		Graphics2D g2 = (Graphics2D)g;
		g2.setStroke(new BasicStroke(1,BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
		if(startPoint != null){
			String[] drawText = text.split("\n", -1);
			Point drawPoint = new Point(startPoint);
			int offset = g.getFont().getSize() + 4;
			int maxLength = 0;
			java.awt.Rectangle bounds = g.getClipBounds();
			int index = 0;
			if(committed){ //static committed string
				for(String s : committedLines){
					g.drawString(s.trim(), drawPoint.x, drawPoint.y);
					drawPoint.y += offset;
				}
			}
			else{ //dynamic word wrapping
				committedLines = new ArrayList<String>();
				for(String s : drawText){
					if(s.trim() != ""){
						double width = g.getFontMetrics().stringWidth(s);
						if(startPoint.x + width + 5 > bounds.width){
							double wrapWidth = wordWrap(s,drawPoint, offset, g, bounds);
							if(wrapWidth > maxLength)maxLength = (int)wrapWidth;
						}
						else{
							if(width > maxLength) maxLength = (int)width;
							committedLines.add(s);
							g.drawString(s, drawPoint.x, drawPoint.y);
							drawPoint.y += offset;
						}
					}
					index++;
				}
			}
			if(maxLength < 2)maxLength = 5;
			int height;
			if(drawPoint.y - startPoint.y < 2) height = offset;
			else height = drawPoint.y - startPoint.y;
			if(!committed){
				g.setColor(Color.black);
				g.drawRect(startPoint.x , startPoint.y - offset, maxLength , height);
			}
		}
	}
	
	//Recursive wordwrap
	//Part 1:
	//Tries to wrap on the last space. If too wide still, tries each successive space inward
	//If substring is fits, write out
	//If smallest substring is too wide, writes out the string up to the first space
	//stores length whenever part1 is drawn to screen
	
	//Part 2:
	//recursively does same procedure the rest of the string
	//if second half is already small enough, writes out
	//stores length whenever part2 is drawn to screen
	//returns the max length between part1 and part2
	//-->returns the width of the longest substring for drawing of the bounding rectangle
	private double wordWrap(String s, Point drawPoint,int offset, Graphics g, java.awt.Rectangle bounds){
		s = s.trim();
		int replace = s.lastIndexOf(" ");
		if(replace < 1){
			committedLines.add(s);
			g.drawString(s.trim(), drawPoint.x, drawPoint.y);
			drawPoint.y += offset;
			return g.getFontMetrics().stringWidth(s);
		}
		double s1Length = 0;
		double s2Length = 0;
		double width = 0;
		
		//Part 1
		if(replace > 0 && replace < s.length()){
			String s1 = s.substring(0, replace).trim();
			width = g.getFontMetrics().stringWidth(s1);
			while(startPoint.x + width +5 > bounds.width){
				replace = s1.lastIndexOf(" ");
				if(replace < 0){
					s1 = s.substring(0, s.lastIndexOf(" ")).trim();
					replace = s.indexOf(" ");
					break;
				}
				s1 = s.substring(0, replace);
				width = g.getFontMetrics().stringWidth(s1);
			}
			committedLines.add(s1);
			g.drawString(s1.trim(), drawPoint.x, drawPoint.y);
			drawPoint.y += offset;
			if(width > s1Length)
				s1Length =width;
			
			if(!s.trim().contains(" ") && replace < 1) return s1Length; //can't wrap anymore, s doesn't have spaces
			
			//Part 2
			String s2 = s.substring(replace, s.length()).trim();
			width = g.getFontMetrics().stringWidth(s2);
			if(startPoint.x + width > bounds.width){
				s2Length = wordWrap(s2, drawPoint, offset, g, bounds);
			}
			else{
				committedLines.add(s2);
				g.drawString(s2.trim(), drawPoint.x, drawPoint.y);
				drawPoint.y += offset;
				
				if(width > s2Length)
					s2Length = width;
			}
		}
		if(s1Length > s2Length) return s1Length;
		else return s2Length;
	}
	
	@Override
	public void start(Point p) {
		if(text.trim() == "")
			startPoint = p;
	}

	@Override
	public void step(Point p) {
		if(!dragging) dragging = true;
		startPoint = new Point(p);
	}
	
	public void step(KeyEvent e){
		if(startPoint != null){
			char c = e.getKeyChar();
			if(c == KeyEvent.VK_BACK_SPACE){
				if(text.length() > 0 &&text.substring(text.length() -1, text.length()) == "\n")
					text = text.substring(0, text.length()-2);
				else
					text = text.substring(0, text.length()-1);
			}
			else if(c == KeyEvent.VK_ENTER){
				text += '\n';
			}
			else if(e.isActionKey() || (new Integer(c)) == 65535) //control/shift/alt are 65535
				return;
			else
				text += c;
		}	
	}
	
	boolean committed = false;
	boolean clickOnce = false;
	public boolean commit() {
	//make sure they click again after starting the text input
		if(dragging){
			dragging = false;
			return false;
		}
		if(!clickOnce){
			clickOnce = true;
			return false;
	 	}
		committed = true;
		return true;
	 }

}
